// 
// BrowseServiceDialog.cs
//
// Copyright © 2008 Philippe Durand <draekz@gmail.com>
// Copyright © 2009 Jiří Zárevúcky <zarevucky.jiri@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Collections.Generic;

using Gtk;
using Glade;

using Galaxium.Core;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

using Anculus.Core;

using Galaxium.Protocol.Xmpp.Library;
using Galaxium.Protocol.Xmpp.Library.Core;
using Galaxium.Protocol.Xmpp.Library.Extensions.Disco;

namespace Galaxium.Protocol.Xmpp.GtkGui
{
	public sealed class BrowseServiceDialog
	{
		[Widget ("BrowseServiceDialog")]
		private Dialog _dialog;
		[Widget ("DialogImage")]
		private Image _dialog_image;
		[Widget ("ServiceEntry")]
		private Entry _service_entry;
		[Widget ("ServiceTree")]
		private TreeView _service_tree;
		[Widget ("BrowseButton")]
		private Button _browse_button;
		[Widget ("JoinButton")]
		private Button _join_button;
		[Widget ("CloseButton")]
		private Button _close_button;

		private ListStore _service_store;
		
		private DiscoNode _node;
		
		public BrowseServiceDialog (DiscoNode node)
		{
			_node = node;
			
			var gxml = new XML (null, "BrowseServiceDialog.glade", null, null);
			gxml.Autoconnect (this);
			
			// GtkUtility.EnableComposite (_dialog);
			
			_service_store = new ListStore (typeof (DiscoNode));
			_service_tree.Model = _service_store;
 			_service_tree.HeadersVisible = true;
 			_service_tree.Selection.Changed += ServiceSelectionChanged;
 			
			var id_column    = new Gtk.TreeViewColumn ();
			var id_cell      = new Gtk.CellRendererText ();
			var id_icon_cell = new Gtk.CellRendererPixbuf ();
			id_column.Title = "ID";
			id_column.PackStart (id_icon_cell, false);
			id_column.PackStart (id_cell, true);
			id_column.MaxWidth = 150;
			id_column.MinWidth = 100;
			
			var name_column = new Gtk.TreeViewColumn ();
			var name_cell   = new Gtk.CellRendererText ();
			name_column.Title = "Name";
			name_column.PackStart (name_cell, true);
			
			id_column.SetCellDataFunc (id_cell, (TreeCellDataFunc) RenderId);
			id_column.SetCellDataFunc (id_icon_cell, (TreeCellDataFunc) RenderIdIcon);
			name_column.SetCellDataFunc (name_cell, (TreeCellDataFunc) RenderName);
			
			_service_tree.AppendColumn (id_column);
			_service_tree.AppendColumn (name_column);
			
			_dialog.Icon = IconUtility.GetIcon ("search-services", IconSizes.Small);
			_dialog_image.Pixbuf = IconUtility.GetIcon ("search-services", IconSizes.Large);
			
			_browse_button.Clicked += BrowseClicked;
			_service_entry.Changed += ServiceChanged;
			_service_entry.Text = _node.Jid;
			
			_node.ChildrenReceivedEvent += HandleChildrenReceived;
			_node.ChildrenErrorOccured += HandleChildrenError;

			_node.RequestChildren ();
			
			_join_button.Clicked += JoinClicked;
			
			_dialog.ShowAll ();
		}

		private void HandleChildrenReceived (object sender, EventArgs args)
		{
			foreach (var node in _node) {
				ThreadUtility.Dispatch (() => {
					_service_store.AppendValues (node);
			
					TreeIter iter;
					if (_service_tree.Model.GetIterFirst (out iter))
						_service_tree.Selection.SelectIter(iter);
				});
			}
		}

		private void HandleChildrenError (object sender, StanzaErrorEventArgs error)
		{
			// TODO
		}
		
		private void RenderIdIcon (Gtk.TreeViewColumn column, Gtk.CellRenderer cell,
		                           Gtk.TreeModel model, Gtk.TreeIter iter)
		{
			var pixbuf = IconUtility.GetIcon ("service-unknown", IconSizes.Small);
			(cell as Gtk.CellRendererPixbuf).Pixbuf = pixbuf;
		}
		
		private void RenderId (Gtk.TreeViewColumn column, Gtk.CellRenderer cell,
		                       Gtk.TreeModel model, Gtk.TreeIter iter)
		{
			var node = (DiscoNode) model.GetValue (iter, 0);
			var id = node.Jid;
			if (node.Node != null)
				id += "#" + node.Node;
			
			(cell as Gtk.CellRendererText).Text = id;
			(cell as Gtk.CellRendererText).Ellipsize = Pango.EllipsizeMode.End;
		}
		 
		private void RenderName (Gtk.TreeViewColumn column, Gtk.CellRenderer cell,
		                         Gtk.TreeModel model, Gtk.TreeIter iter)
		{
			var node = (DiscoNode) model.GetValue (iter, 0);
			
			(cell as Gtk.CellRendererText).Text = node.Name;
			(cell as Gtk.CellRendererText).Ellipsize = Pango.EllipsizeMode.End;
		}
		
		public int Run()
		{
			return _dialog.Run();
		}
		
		public void Destroy()
		{
			_node.ChildrenReceivedEvent -= HandleChildrenReceived;
			_node.ChildrenErrorOccured -= HandleChildrenError;
			_dialog.Destroy();
		}
		
		private void JoinClicked (object sender, EventArgs args)
		{
			
		}
		
		private void BrowseClicked (object sender, EventArgs args)
		{
			_service_store.Clear ();


			
			_node.RequestChildren ();
		}
		
		private void ServiceSelectionChanged (object sender, EventArgs args)
		{
			if (_service_tree.Selection == null) return;
			
			TreeIter iter;
			_service_tree.Selection.GetSelected (out iter);
			
			if (iter.Stamp == TreeIter.Zero.Stamp) return;
			
			var node = (DiscoNode) _service_tree.Model.GetValue (iter, 0);
				
			if (node == null) return;

			// We have found a selected service.
			//_browseButton.Sensitive = identity.Service.CanBrowse;
			//_join_button.Sensitive = identity.Service.CanJoin;
			//_registerButton.Sensitive = identity.Service.CanRegister;
		}
		
		private void ServiceChanged (object sender, EventArgs args)
		{
			_browse_button.Sensitive = _service_entry.Text != String.Empty;
		}
	}
}
